~ chicken-core (chicken-5) /manual/Accessing external objects


 1[[tags: manual]]
 2
 3[[toc:]]
 4
 5== Accessing externally defined data
 6
 7For a list of the special forms that allow definition of Scheme procedures
 8that access native C/C++ code, consult the documentation on the
 9[[Module (chicken foreign)|(chicken foreign)]] module. The remainder
10of this chapter merely explains a few special cases.
11
12== Returning large objects or chunks of memory to Scheme
13
14When you call a C function which needs to return quantities of data, several issues arise:
15* the size of the nursery is limited, so {{C_alloc}} can cause stack overflow
16* if you malloc in C, and intend to leave it there, and directly access parts of that data from Scheme, you will need C accessor functions to pinpoint the parts you need and return them as Scheme objects; you will also need a finalizer if you intend for this data to be garbage-collected
17* building up lists or other complex Scheme structures from individual pairs, or putting non-immediate objects into vectors, is cumbersome in C
18
19So some would advise you to just return a pointer to Scheme, use memcpy or any other function(s) which you need to get the data into CHICKEN-managed memory and into the desired kind of data structure, then free the C data.  For this example, we are trying to return an array of doubles into an {{f64vector}}; we can accomplish that by adding a specialized copy function to the C library being integrated:
20
21<enscript highlight=C>
22void CopyResults(double* vector) {
23    memcpy(vector, bezierBuffer, totalOutputPoints * sizeof(double));
24}
25
26// The original C function which takes an array of doubles, 
27// does some sort of transmogrification,
28// retains a new malloc'd array of the results
29// and returns the count
30int GenerateResults(double* vector, int count) {
31    ... 
32}
33</enscript>
34
35and the "egg" which calls the C functions can be implemented like this:
36
37<enscript highlight=scheme>
38(module memcpy-demo (input->output)
39    (import (chicken base) scheme (chicken foreign) srfi-4)
40
41    (define CopyResults (foreign-lambda void "CopyResults" f64vector))
42
43    (define GenerateResults (foreign-lambda integer "GenerateResults" f64vector integer))
44
45    (define (input->output input)
46        (let* ([size (GenerateResults input (f64vector-length input))] 
47               [vect (make-f64vector size)])
48            (printf "returned size ~a~%" size)
49            (CopyResults vect)
50            vect)))
51
52</enscript>
53
54The foreign-lambda takes care of the details in this case so that an f64vector allocated in the nursery can be treated as a plain old array of doubles in C (assuming your C compiler uses 64-bit values for double).
55
56Various eggs provide other examples, and some of them do it more efficiently too, but this method is relatively clean and compact.
57
58---
59Previous: [[Interface to external functions and variables]]
60
61Next: [[Foreign type specifiers]]
Trap